package com.qisu.socket.server;

import java.net.InetSocketAddress;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;

/**
 * 
 * @author alsan
 *
 */
@Component
@Configuration
public class NettyConfigure {
	@Value("${netty.tcp.port}") private int _tcpPort;
	@Value("${netty.master}") private int _bossCount;
	@Value("${netty.worker}") private int _workerCount;

	@Autowired ServerChannelInitializer _channelInitializer;

	@Bean("serverBootStrap")
	// @formatter:off
	public ServerBootstrap serverBootstrap(
		@Value("${netty.tcp.nodelay}") boolean _tcpNoDelay,
		@Value("${netty.so.linger}") int _linger,
		@Value("${netty.so.rcvbuf}") int _rcvBuf,
		@Value("${netty.so.senbuf}") int _sndBuf,
		@Value("${netty.so.keepalive}") boolean _keepAlive,
		@Value("${netty.so.backlog}") int _backlog,
		@Value("${netty.so.reuseaddr}") boolean _reuseAddr
	) {
		ServerBootstrap bootstrap = new ServerBootstrap();

		bootstrap.group(bossGroup(), workerGroup())
				.channel(NioServerSocketChannel.class)
				.option(ChannelOption.TCP_NODELAY, _tcpNoDelay)
				.option(ChannelOption.SO_REUSEADDR, _reuseAddr)
				.option(ChannelOption.SO_KEEPALIVE, _keepAlive)
				.option(ChannelOption.SO_LINGER, _linger)
				.option(ChannelOption.SO_RCVBUF, _rcvBuf)
				.option(ChannelOption.SO_SNDBUF, _sndBuf)
				.childHandler(_channelInitializer);

		return bootstrap;
	}
	// @formatter:on

	@Bean("masterGroup")
	public NioEventLoopGroup bossGroup() {
		return new NioEventLoopGroup(_bossCount);
	}

	@Bean("workerGroup")
	public NioEventLoopGroup workerGroup() {
		return new NioEventLoopGroup(_workerCount);
	}

	@Bean("tcpSocketAddress")
	public InetSocketAddress tcpPort() {
		return new InetSocketAddress(_tcpPort);
	}
}
